#include <stdint.h>
#include "mode_buffer.c"
#include "massage_bsp.h"
#include "massage_cfg.h"

uint8_t *p_msg_mode;
msg_para_t msg_para[MSG_DEV_NUM];

// port layer
void Msg_Status_Get(void);
void Msg_Init_Port(void);
void Msg_Opt_Port(uint8_t dev, msg_pos_t pos_sel, msg_sta_t sta);
void Msg_Oc_Check_Opt_Port(uint8_t dev, msg_pos_t pos_sel, msg_sta_t sta);
uint32_t Msg_Clk_Get(void);
void Msg_Pos_Num_Get(void);

void Msg_Init(void)
{
    memset(&msg_para[0], 0, sizeof(msg_para_t)*MSG_DEV_NUM);
    #if MSG_STATUS_CHECK
        Msg_Status_Get();
        Msg_Pos_Num_Get();
    #endif
    Msg_Init_Port();
    // default set
    {
        for (uint8_t i = 0; i < MSG_DEV_NUM; i++) {
            msg_para[i].mode_sw_type = MSG_AUTO;
			msg_para[i].mode = MSG_MODE_1;
			msg_para[i].manual_mode = MSG_MODE_1;
            #if MSG_STRE_CONTROL
                msg_para[i].intensity = msg_stre[1];
            #else
                msg_para[i].intensity = MSG_DEFAULT_STRE;
            #endif
			msg_para[i].head_en_flag = MSG_OPEN;
			msg_para[i].oc_flag = MSG_UNOVER;
			msg_para[i].work_time = MSG_WORK_TIME;	
            #if MSG_MODE2_ADJUSTABLE_SPEED
                msg_para[i].mode2_sw_time = 0;
            #else
                msg_para[i].mode2_sw_time = mode_sw_time[MSG_MODE_2 - 1];
            #endif
            msg_para[i].msg_point_pos = MSG_POS_HEAD;
            msg_para[i].point_en_flag = FALSE;
            msg_para[i].msg_point.pos_ctl = 0;
        }
    }
}

#if MSG_STATUS_CHECK
void Msg_Pos_Num_Get(void)
{
    uint8_t temp;
    for (uint8_t i = 0; i < MSG_DEV_NUM; i++) {
        temp = ~msg_para[i].msg_install.pos_ctl & 0x3f;
        for (uint8_t j = 0; j < 6; j ++) {
            msg_para[i].msg_pos_num += (temp & 0x01);
            temp = temp >> 1;
        }
    }
}
#endif

#if MSG_OVER_CURRENT_DETECTION
static void Msg_Set_Oc_Value(uint8_t dev, msg_mode_oc_value_t msg_mode)
{
    uint8_t oc_pos_num = 0;
    msg_vc_dac_config_t     stcdacConfig;
    DDL_ZERO_STRUCT(stcdacConfig);

    if (msg_mode == NORMAL_MODE) {
        if ((msg_para[dev].mode == MSG_MODE_4) || (msg_para[dev].mode == MSG_MODE_3)) {
            #if MSG_OC_VALUE_FOR_5V
                stcdacConfig.u8DivVal       = msg_oc_value[msg_para[dev].mode - 1];
            #else
                // 通过测试发现，当芯片电压为3.3V，并且在马达的模式三和模式四进行短路时，当已经判断为短路的马达部位大于3个时，需要将该模式下过流阈值调低，否则继续短路会出现烧坏板子的现象！
                uint8_t temp = msg_para[dev].oc.pos_ctl & 0x3f;
                for (uint8_t i = 0; i < 6; i ++) {
                    oc_pos_num += (temp & 0x01);
                    temp = temp >> 1;
                }
                if (oc_pos_num > 3) {
                    stcdacConfig.u8DivVal       = msg_oc_value[msg_para[dev].mode - 1] - 2;
                } else {
                    stcdacConfig.u8DivVal       = msg_oc_value[msg_para[dev].mode - 1];
                }
            #endif
        } else if (msg_para[dev].mode == MSG_MODE_8) {
            if ((msg_para[dev].pos.pos_ctl | msg_para[dev].msg_install.pos_ctl) == 0x3f) {
                #if MSG_OC_VALUE_FOR_5V
                    stcdacConfig.u8DivVal       = msg_oc_value[msg_para[dev].mode - 1] + MSG_MODE8_OC_ADD_VALUE;
                #else
                    uint8_t temp = msg_para[dev].oc.pos_ctl & 0x3f;
                    for (uint8_t i = 0; i < 6; i ++) {
                        oc_pos_num += (temp & 0x01);
                        temp = temp >> 1;
                    }
                    if (oc_pos_num > 3) {
                        // 通过测试发现，当芯片电压为3.3V，并且在马达的模式八进行短路时，当已经判断为短路的马达部位大于3个时，需要将该模式下过流阈值调低，否则继续短路会出现烧坏板子的现象！
                        stcdacConfig.u8DivVal       = msg_oc_value[msg_para[dev].mode - 1] + MSG_MODE8_OC_ADD_VALUE - 2;
                    } else {
                        // MSG_MODE8_OC_ADD_VALUE为模式8时，马达部位模式切换发生突变（即当从一个马达工作突然切换到全部马达工作）时，对过流检测阈值的补偿
                        stcdacConfig.u8DivVal       = msg_oc_value[msg_para[dev].mode - 1] + MSG_MODE8_OC_ADD_VALUE;
                    }
                #endif
            } else {
                stcdacConfig.u8DivVal       = msg_oc_value[msg_para[dev].mode - 1];
            }
        } else {
            stcdacConfig.u8DivVal       = msg_oc_value[msg_para[dev].mode - 1];
        }
    } else if (msg_mode == POINT_MODE) {
        stcdacConfig.u8DivVal       = MSG_POINT_OC_VALUE;
    } else if (msg_mode == OC_CHECK_MODE) {
        stcdacConfig.u8DivVal       = MSG_OC_CHECK_OC_VALUE;
    }
    stcdacConfig.bDivEn         = TRUE;
    stcdacConfig.enDivVref      = VcDivVrefAvcc;
    Msg_Set_Div_Value(&stcdacConfig);
}
#endif

static void Msg_Sw_Mode_Type(uint8_t dev, uint8_t sw_mode)
{
	switch (sw_mode) {

		case MSG_MODE_1 : {
			if (++msg_para[dev].mode_type > (sizeof(msg_mode1) / sizeof(msg_mode1[0])) - 1) {
				msg_para[dev].mode_type = 0;
			}
			break;
		}

		case MSG_MODE_2 : {
			if (++msg_para[dev].mode_type > (sizeof(msg_mode2) / sizeof(msg_mode2[0])) - 1) {
				msg_para[dev].mode_type = 0;
			}
			break;
		}

		case MSG_MODE_3 : {
			if (++msg_para[dev].mode_type > (sizeof(msg_mode3) / sizeof(msg_mode3[0])) - 1) {
				msg_para[dev].mode_type = 0;
			}
			break;
		}

		case MSG_MODE_4 : {
			if (++msg_para[dev].mode_type > (sizeof(msg_mode4) / sizeof(msg_mode4[0])) - 1) {
				msg_para[dev].mode_type = 0;
			}
			break;
		}

		case MSG_MODE_5 : {
			if (++msg_para[dev].mode_type > (sizeof(msg_mode5) / sizeof(msg_mode5[0])) - 1) {
				msg_para[dev].mode_type = 0;
			}
			break;
		}

		case MSG_MODE_6 : {
			if (++msg_para[dev].mode_type > (sizeof(msg_mode6) / sizeof(msg_mode6[0])) - 1) {
				msg_para[dev].mode_type = 0;
			}
			break;
		}

		case MSG_MODE_7 : {
			if (++msg_para[dev].mode_type > (sizeof(msg_mode7) / sizeof(msg_mode7[0])) - 1) {
				msg_para[dev].mode_type = 0;
			}
			break;
		}

		case MSG_MODE_8 : {
			if (++msg_para[dev].mode_type > (sizeof(msg_mode8) / sizeof(msg_mode8[0])) - 1) {
				msg_para[dev].mode_type = 0;
			}
			break;
		}

		case MSG_MODE_9 : {
			if (++msg_para[dev].mode_type > (sizeof(msg_mode9) / sizeof(msg_mode9[0])) - 1) {
				msg_para[dev].mode_type = 0;
			}
			break;
		}

		case MSG_MODE_10 : {
			if (++msg_para[dev].mode_type > (sizeof(msg_mode10) / sizeof(msg_mode10[0])) - 1) {
				msg_para[dev].mode_type = 0;
			}
			break;
		}

		default :
		    break;

	}
}

static void Msg_Set_On_Or_Off(uint8_t dev, msg_sta_t sta)
{
    switch (sta) {
        case MSG_CLOSE: {
            for (uint8_t i = 0; i < MSG_DEV_NUM; i++) {
				Msg_Opt_Port(i, MSG_POS_HEAD, MSG_CLOSE);
                Msg_Opt_Port(i, MSG_POS_BACK, MSG_CLOSE);
                Msg_Opt_Port(i, MSG_POS_LOIN, MSG_CLOSE);
				Msg_Opt_Port(i, MSG_POS_HIP, MSG_CLOSE);
                Msg_Opt_Port(i, MSG_POS_LEG, MSG_CLOSE);
                Msg_Opt_Port(i, MSG_POS_FOOT, MSG_CLOSE);		
            }

            msg_para[dev].work_sta = MSG_CLOSE;
			msg_para[dev].work_time = 0XFF;
            #if MSG_POS_LED
                msg_para[dev].msg_pos_led = 0X00;
            #endif
			msg_para[dev].oc.pos_ctl = 0X00;
            #if MSG_STRE_CONTROL
                msg_para[dev].intensity = msg_stre[0];
            #else
                msg_para[dev].intensity = 0;
            #endif
            break;
        }

        case MSG_OPEN: {
            msg_para[dev].auto_sw_cnt = Msg_Clk_Get();
            msg_para[dev].mode_sw_cnt = Msg_Clk_Get();
			msg_para[dev].mode_sw_type = MSG_AUTO;
            msg_para[dev].mode = MSG_MODE_1;
            msg_para[dev].work_sta = MSG_OPEN;
            msg_para[dev].fre_cnt = 0;
            msg_para[dev].mode_type = 0;
            #if MSG_MODE2_ADJUSTABLE_SPEED
                msg_para[dev].mode2_sw_cnt = 0;
                msg_para[dev].mode2_sw_time = 0;
            #else
                msg_para[dev].mode2_sw_time = mode_sw_time[MSG_MODE_2 - 1];
            #endif
			msg_para[dev].work_time = MSG_WORK_TIME;
            msg_para[dev].oc_flag = MSG_UNOVER;
            #if MSG_STRE_CONTROL
                msg_para[dev].intensity = msg_stre[1];
            #else
                msg_para[dev].intensity = MSG_DEFAULT_STRE;
            #endif
            msg_para[dev].msg_point_pos = MSG_POS_HEAD;
            msg_para[dev].point_en_flag = FALSE;
            msg_para[dev].msg_point.pos_ctl = 0;
            // 在马达刚启动的时候，先将原模式一切换时间保存下来，然后将切换时间归零，以确保马达刚启动时，不需要等待！
            msg_para[dev].mode1_sw_time_backups = mode_sw_time[MSG_MODE_1 - 1];
            mode_sw_time[MSG_MODE_1 - 1] = 0;
            break;
        }
        default: {
            break;
        }
    }
}

static void Msg_Set_Run_Mode(uint8_t dev, msg_run_mode_t msg_run_mode)
{
	msg_para[dev].mode_sw_type = msg_run_mode;
}

static void Msg_Manual_Set_Mode(uint8_t dev, msg_mode_t manual_mode)
{
    if (manual_mode > MSG_MODE_NUM) {
        msg_para[dev].manual_mode = MSG_MODE_1;
        return;
    }
	msg_para[dev].manual_mode = manual_mode;
	msg_para[dev].manual_sw_mode_flag = TRUE;
}

static void Msg_Set_Time(uint8_t dev, uint8_t work_time)
{
	msg_para[dev].work_time = work_time;
}

#if MSG_STRE_CONTROL
    static void Msg_Set_Stre(uint8_t dev, msg_stre_t stre)
    {
        if (stre > MSG_STRE_NUM) {
            msg_para[dev].intensity = msg_stre[10];
            return;
        }
        if (msg_para[dev].mode != MSG_MODE_10) {
            msg_para[dev].stre = stre;
            msg_para[dev].intensity = msg_stre[stre];
            msg_para[dev].intensity_backups = msg_para[dev].intensity; //马达强度备份值，当模式10工作完之后，切换到其他模式时，将马达强度恢复
        }
    }
#endif

#if MSG_HEAD_CONTROL
    static void Msg_Set_Head_En(uint8_t dev, msg_sta_t head_flag)
    {
        msg_para[dev].head_en_flag = head_flag;
    }
#endif

#if MSG_POINT_CONTROL
    static void Msg_Set_Point_En(uint8_t dev, msg_pos_t point_flag)
    {
        #if MSG_POINT_LOOP
            // 若点动模式使能循环功能，则一直在马达的六个部位循环点动；否则，当点动到最后一个部位之后，将自动退出点动模式，恢复到正常模式
            if (msg_para[dev].msg_point_pos == MSG_POS_NONE) {
                msg_para[dev].msg_point_pos = MSG_POS_HEAD;
            }
        #endif
        msg_para[dev].point_en_flag = point_flag;
        if (msg_para[dev].point_en_flag) {
            msg_para[dev].msg_point.pos_ctl = 0;
            switch (msg_para[dev].msg_point_pos) {
                case MSG_POS_FOOT :
                case MSG_POS_LEG :
                case MSG_POS_HIP :
                case MSG_POS_LOIN :
                case MSG_POS_BACK :
                case MSG_POS_HEAD : {
                    if ((msg_para[dev].msg_point_pos == MSG_POS_HEAD) || (msg_para[dev].msg_point_pos == MSG_POS_LOIN)) {
                        msg_para[dev].msg_point_pos -= 1;
                    }
                    // 判断当前的马达部位对应电阻是否为NC，若是，则该点动部位自动跳过，下同
                    if (!(msg_para[dev].msg_install.pos_ctl & ((1) << (msg_para[dev].msg_point_pos - 1)))) {
                        msg_para[dev].msg_point.pos_ctl = (1) << (msg_para[dev].msg_point_pos - 1);
                        msg_para[dev].msg_point_pos -= 1;
                        msg_para[dev].pos.pos_ctl = msg_para[dev].msg_point.pos_ctl;
                        #if MSG_POS_LED
                            msg_para[dev].msg_pos_led = msg_para[dev].pos.pos_ctl;
                        #endif
                    } else {
                        if (msg_para[dev].msg_point_pos == MSG_POS_FOOT) {
                            goto exit;
                        }
                        if (!(msg_para[dev].msg_install.pos_ctl & ((1) << (msg_para[dev].msg_point_pos - 2)))) {
                            msg_para[dev].msg_point.pos_ctl = (1) << (msg_para[dev].msg_point_pos - 2);
                            msg_para[dev].msg_point_pos -= 2;
                            msg_para[dev].pos.pos_ctl = msg_para[dev].msg_point.pos_ctl;
                            #if MSG_POS_LED
                                msg_para[dev].msg_pos_led = msg_para[dev].pos.pos_ctl;
                            #endif
                        } else {
                            if (msg_para[dev].msg_point_pos == MSG_POS_LEG) {
                                goto exit;
                            }
                            if (!(msg_para[dev].msg_install.pos_ctl & ((1) << (msg_para[dev].msg_point_pos - 3)))) {
                                msg_para[dev].msg_point.pos_ctl = (1) << (msg_para[dev].msg_point_pos - 3);
                                msg_para[dev].msg_point_pos -= 3;
                                msg_para[dev].pos.pos_ctl = msg_para[dev].msg_point.pos_ctl;
                                #if MSG_POS_LED
                                    msg_para[dev].msg_pos_led = msg_para[dev].pos.pos_ctl;
                                #endif
                            } else {
                                if (msg_para[dev].msg_point_pos == MSG_POS_HIP) {
                                    goto exit;
                                }
                                if (!(msg_para[dev].msg_install.pos_ctl & ((1) << (msg_para[dev].msg_point_pos - 4)))) {
                                    msg_para[dev].msg_point.pos_ctl = (1) << (msg_para[dev].msg_point_pos - 4);
                                    msg_para[dev].msg_point_pos -= 4;
                                    msg_para[dev].pos.pos_ctl = msg_para[dev].msg_point.pos_ctl;
                                    #if MSG_POS_LED
                                        msg_para[dev].msg_pos_led = msg_para[dev].pos.pos_ctl;
                                    #endif
                                } else {
                                    if (msg_para[dev].msg_point_pos == MSG_POS_LOIN) {
                                        goto exit;
                                    }
                                    if (!(msg_para[dev].msg_install.pos_ctl & ((1) << (msg_para[dev].msg_point_pos - 5)))) {
                                        msg_para[dev].msg_point.pos_ctl = (1) << (msg_para[dev].msg_point_pos - 5);
                                        msg_para[dev].msg_point_pos -= 5;
                                        msg_para[dev].pos.pos_ctl = msg_para[dev].msg_point.pos_ctl;
                                        #if MSG_POS_LED
                                            msg_para[dev].msg_pos_led = msg_para[dev].pos.pos_ctl;
                                        #endif
                                    } else {
                                        if (msg_para[dev].msg_point_pos == MSG_POS_BACK) {
                                            goto exit;
                                        }
                                        if (!(msg_para[dev].msg_install.pos_ctl & ((1) << (msg_para[dev].msg_point_pos - 6)))) {
                                            msg_para[dev].msg_point.pos_ctl = (1) << (msg_para[dev].msg_point_pos - 6);
                                            msg_para[dev].msg_point_pos -= 6;
                                            msg_para[dev].pos.pos_ctl = msg_para[dev].msg_point.pos_ctl;
                                            #if MSG_POS_LED
                                                msg_para[dev].msg_pos_led = msg_para[dev].pos.pos_ctl;
                                            #endif
                                        } else {
                                        exit:
                                            #if MSG_POINT_LOOP
                                                msg_para[dev].msg_point_pos -= 1;
                                            #else
                                                msg_para[dev].msg_point_pos = MSG_POS_HEAD;
                                                msg_para[dev].point_en_flag = FALSE;
                                                msg_para[dev].msg_point.pos_ctl = 0;
                                                #if MSG_OVER_CURRENT_DETECTION
                                                    // 在退出点动模式之前，需将马达过流检测阈值调整到正常模式时的阈值
                                                    if (msg_para[dev].oc_flag == MSG_UNOVER) {
                                                        Msg_Set_Oc_Value(dev, NORMAL_MODE);
                                                    }
                                                #endif
                                                // 在退出点动模式时，将马达各个部位的使能以及对于LED灯的使能恢复为正常模式
                                                msg_para[dev].pos.pos_ctl = (p_msg_mode [msg_para[dev].mode_type] & (~msg_para[dev].msg_install.pos_ctl));
                                                #if MSG_POS_LED
                                                    msg_para[dev].msg_pos_led = msg_para[dev].pos.pos_ctl;
                                                #endif
                                            #endif
                                        }
                                    }
                                }
                            }
                        }
                    }
                    break;
                }

                default : {
                    if (msg_para[dev].msg_point_pos == MSG_POS_NONE) {
                        msg_para[dev].msg_point_pos = MSG_POS_HEAD;
                        msg_para[dev].point_en_flag = FALSE;
                        msg_para[dev].msg_point.pos_ctl = 0;
                        #if MSG_OVER_CURRENT_DETECTION
                            if (msg_para[dev].oc_flag == MSG_UNOVER) {
                                Msg_Set_Oc_Value(dev, NORMAL_MODE);
                            }
                        #endif
                        msg_para[dev].pos.pos_ctl = (p_msg_mode [msg_para[dev].mode_type] & (~msg_para[dev].msg_install.pos_ctl));
                        #if MSG_POS_LED
                            msg_para[dev].msg_pos_led = msg_para[dev].pos.pos_ctl;
                        #endif
                    }
                    break;
                }
            }
        } else {
            // 取消点动功能，即退出点动循环
            msg_para[dev].msg_point_pos = MSG_POS_HEAD;
            msg_para[dev].msg_point.pos_ctl = 0;
            #if MSG_OVER_CURRENT_DETECTION
                if (msg_para[dev].oc_flag == MSG_UNOVER) {
                    Msg_Set_Oc_Value(dev, NORMAL_MODE);
                }
            #endif
            msg_para[dev].pos.pos_ctl = (p_msg_mode [msg_para[dev].mode_type] & (~msg_para[dev].msg_install.pos_ctl));
            #if MSG_POS_LED
                msg_para[dev].msg_pos_led = msg_para[dev].pos.pos_ctl;
            #endif
        }
    }
#endif

void Msg_Opt(uint8_t dev, msg_cmd_t cmd, void *arg)
{
	switch (cmd) {

		case M_SET_ON_OR_OFF:{
			msg_sta_t msg_ctl_sta = *(msg_sta_t*)arg;
			Msg_Set_On_Or_Off(dev, msg_ctl_sta);
			break;
		}

		case M_SET_RUN_MODE:{
			msg_run_mode_t msg_run_mode = *(msg_run_mode_t*)arg;
			Msg_Set_Run_Mode(dev, msg_run_mode);
			break;
		}
		
		case M_SET_MANUAL_MODE:{
			msg_mode_t msg_manual_mode = *(msg_mode_t*)arg;
			Msg_Manual_Set_Mode(dev, msg_manual_mode);
			break;
		}

		case M_SET_TIME:{
			unsigned char msg_work_time = *(unsigned char*)arg;
			Msg_Set_Time(dev, msg_work_time);
			break;
		}

        #if MSG_STRE_CONTROL
            case M_SET_STRE:{
                msg_stre_t msg_stre = *(msg_stre_t*)arg;
                Msg_Set_Stre(dev, msg_stre);
                break;
            }
        #endif

        #if MSG_HEAD_CONTROL
            case M_SET_HEAD_EN:{
                msg_sta_t msg_head_sta = *(msg_sta_t*)arg;
                Msg_Set_Head_En(dev, msg_head_sta);
                break;
            }
        #endif

        #if MSG_POINT_CONTROL
            case M_SET_POINT:{
                msg_pos_t msg_point_flag = *(unsigned char*)arg;
                Msg_Set_Point_En(dev, msg_point_flag);
                break;
            }
        #endif

		default:
			break;
	}
}

void Msg_Get_Info(msg_info_t *info)
{
    for (uint8_t i = 0; i < MSG_DEV_NUM; i++) {
        info->mode[i] = msg_para[i].mode;
        info->work_sta[i] = msg_para[i].work_sta;
        info->work_time[i] = msg_para[i].work_time;
        #if MSG_POS_LED
            info->msg_pos_led[i] = msg_para[i].msg_pos_led;
        #endif
    }
}

#if MSG_OVER_CURRENT_DETECTION
    static void Msg_Over_Current_Detection_Scan(void)
    {
        for (uint8_t i = 0; i < MSG_DEV_NUM; i++) {
            if (!msg_para[i].work_sta) 
                continue;

            if (msg_para[i].oc_flag) {
                msg_para[i].oc_check_tout.clk = Msg_Clk_Get();
                if ((unsigned int)(msg_para[i].oc_check_tout.clk - msg_para[i].oc_check_tout.cnt) >= msg_para[i].oc_check_tout.record) {
                    if (++ msg_para[i].msg_pos > MSG_POS_NUM) {
                        msg_para[i].msg_pos = MSG_POS_FOOT;
                        msg_para[i].oc_check_tout.time ++;
                    }

                    msg_para[i].oc_check.pos_ctl = 0;
                    msg_para[i].oc_check_tout.record = MSG_OVER_CURRENT_CHECK_TIME;
                    msg_para[i].oc_check_tout.cnt = msg_para[i].oc_check_tout.clk;
                   
                    if (msg_para[i].msg_pos == MSG_POS_FOOT) {
                        Msg_Oc_Check_Opt_Port(i, MSG_POS_HEAD, MSG_CLOSE);
                    } else {
                        Msg_Oc_Check_Opt_Port(i, (msg_para[i].msg_pos - 1), MSG_CLOSE);
                    }

                    if (msg_para[i].oc.pos_ctl & ((1) << (msg_para[i].msg_pos - 1))) {
                        if (msg_para[i].msg_pos ++ > MSG_POS_NUM) {
                            msg_para[i].msg_pos = MSG_POS_FOOT;
                        }
                    }
                    // 避免当模拟比较器中断发生在该函数内所造成的bug（没有发生短路的马达部位被判断为短路的bug）
                    if (!msg_para[i].oc_flag) {
                        msg_para[i].msg_pos = MSG_POS_NONE;
                        msg_para[i].oc_check.pos_ctl = 0;
                        return;
                    }
                    // 当检测到马达第一次短路后，在进行循环十次的点动过流检测中没有再次检测到短路，则自动退出马达过流检测模式，并且将过流检测阈值恢复到正常模式下的阈值
                    if (msg_para[i].oc_check_tout.time >= MSG_OVER_CURRENT_CHECK_CNT) {
                        msg_para[i].msg_pos = MSG_POS_NONE;
                        msg_para[i].oc_flag = MSG_UNOVER;
                        msg_para[i].oc_check_tout.cnt = 0;
                        msg_para[i].oc_check_tout.record = 0;
                        msg_para[i].oc_check_tout.time = 0;
                        Msg_Set_Oc_Value(i, NORMAL_MODE);
                    }

                    switch (msg_para[i].msg_pos) {
                        case MSG_POS_FOOT : 
                        case MSG_POS_LEG : 
                        case MSG_POS_HIP : 
                        case MSG_POS_LOIN : 
                        case MSG_POS_BACK : 
                        case MSG_POS_HEAD : {
                            if ((msg_para[i].oc.pos_ctl & ((1) << (msg_para[i].msg_pos - 1))) == FALSE) {
                                if (msg_para[i].oc_flag) {
                                    msg_para[i].oc_check.pos_ctl = ((1)<< (msg_para[i].msg_pos - 1));
                                    Msg_Oc_Check_Opt_Port(i, msg_para[i].msg_pos, MSG_OPEN);
                                }
                            }
                            break;
                        }

                        default :
                            break;
                    }	
                }
            }
        }
    }

    void Msg_Over_Current_Detection_Int_Process(void)
    {
        for (uint8_t i = 0; i < MSG_DEV_NUM; i++) {
            msg_para[i].oc_flag = MSG_OVER;
            Msg_Oc_Check_Opt_Port(i, MSG_POS_HEAD, MSG_CLOSE);
            Msg_Oc_Check_Opt_Port(i, MSG_POS_BACK, MSG_CLOSE);
            Msg_Oc_Check_Opt_Port(i, MSG_POS_LOIN, MSG_CLOSE);
            Msg_Oc_Check_Opt_Port(i, MSG_POS_HIP, MSG_CLOSE);
            Msg_Oc_Check_Opt_Port(i, MSG_POS_LEG, MSG_CLOSE);
            Msg_Oc_Check_Opt_Port(i, MSG_POS_FOOT, MSG_CLOSE);
           
            #if MSG_POINT_CONTROL
                // 在点动模式下发生马达短路时，进入的马达过流检测模式
                if (msg_para[i].point_en_flag) {
                    if (msg_para[i].msg_point.pos.head) {
                        msg_para[i].oc.pos_ctl |= ((1)<< (MSG_POS_HEAD - 1));
                        msg_para[i].oc_flag = MSG_UNOVER;
                    } else if (msg_para[i].msg_point.pos.back) {
                        msg_para[i].oc.pos_ctl |= ((1)<< (MSG_POS_BACK - 1));
                        msg_para[i].oc_flag = MSG_UNOVER;
                    } else if (msg_para[i].msg_point.pos.loin) {
                        msg_para[i].oc.pos_ctl |= ((1)<< (MSG_POS_LOIN - 1));
                        msg_para[i].oc_flag = MSG_UNOVER;
                    } else if (msg_para[i].msg_point.pos.hip) {
                        msg_para[i].oc.pos_ctl |= ((1)<< (MSG_POS_HIP - 1));
                        msg_para[i].oc_flag = MSG_UNOVER;
                    } else if (msg_para[i].msg_point.pos.leg) {
                        msg_para[i].oc.pos_ctl |= ((1)<< (MSG_POS_LEG - 1));
                        msg_para[i].oc_flag = MSG_UNOVER;
                    } else if (msg_para[i].msg_point.pos.foot) {
                        msg_para[i].oc.pos_ctl |= ((1)<< (MSG_POS_FOOT - 1));
                        msg_para[i].oc_flag = MSG_UNOVER;
                    }
                } else {
            #endif
                    // 在普通模式下发生马达短路时，进入的马达过流检测模式
                    if (msg_para[i].oc_check.pos.head) {
                        msg_para[i].oc.pos_ctl |= ((1)<< (MSG_POS_HEAD - 1));
                        msg_para[i].oc_check.pos_ctl = ((0)<< (MSG_POS_HEAD - 1));
                        msg_para[i].oc_flag = MSG_UNOVER;
                    } else if (msg_para[i].oc_check.pos.back) {
                        msg_para[i].oc.pos_ctl |= ((1)<< (MSG_POS_BACK - 1));
                        msg_para[i].oc_check.pos_ctl = ((0)<< (MSG_POS_BACK - 1));
                        msg_para[i].oc_flag = MSG_UNOVER;
                    } else if (msg_para[i].oc_check.pos.loin) {
                        msg_para[i].oc.pos_ctl |= ((1)<< (MSG_POS_LOIN - 1));
                        msg_para[i].oc_check.pos_ctl = ((0)<< (MSG_POS_LOIN - 1));
                        msg_para[i].oc_flag = MSG_UNOVER;
                    } else if (msg_para[i].oc_check.pos.hip) {
                        msg_para[i].oc.pos_ctl |= ((1)<< (MSG_POS_HIP - 1));
                        msg_para[i].oc_check.pos_ctl = ((0)<< (MSG_POS_HIP - 1));
                        msg_para[i].oc_flag = MSG_UNOVER;
                    } else if (msg_para[i].oc_check.pos.leg) {
                        msg_para[i].oc.pos_ctl |= ((1)<< (MSG_POS_LEG - 1));
                        msg_para[i].oc_check.pos_ctl = ((0)<< (MSG_POS_LEG - 1));
                        msg_para[i].oc_flag = MSG_UNOVER;
                    } else if (msg_para[i].oc_check.pos.foot) {
                        msg_para[i].oc.pos_ctl |= ((1)<< (MSG_POS_FOOT - 1));
                        msg_para[i].oc_check.pos_ctl = ((0)<< (MSG_POS_FOOT - 1));
                        msg_para[i].oc_flag = MSG_UNOVER;
                    }

                    // 在检测到短路的马达部位后，即在退出过流检测模式之前，将马达的过流检测阈值恢复为正常模式下的阈值
                    if (msg_para[i].oc_flag == MSG_UNOVER) {
                        msg_para[i].msg_pos = MSG_POS_NONE;
                        msg_para[i].oc_check_tout.cnt = 0;
                        msg_para[i].oc_check_tout.record = 0;
                        msg_para[i].oc_check_tout.time = 0;
                        Msg_Set_Oc_Value(i, NORMAL_MODE);
                    } else if (msg_para[i].oc_flag == MSG_OVER) {
                    // 在第一次检测到马达短路之后，即在将要进入过流检测模式之前，将马达的过流检测阈值调整为过流检测模式下的阈值
                        Msg_Set_Oc_Value(i, OC_CHECK_MODE);
                    }
            #if MSG_POINT_CONTROL
                }
            #endif
        }
    }
#endif

static void Msg_Scan(void)
{
    for (uint8_t i = 0; i < MSG_DEV_NUM; i++) {
        unsigned int clk = Msg_Clk_Get();
        if (!msg_para[i].work_sta) 
            continue;
        // auto switch mode
        msg_para[i].overflow_value = (uint32_t)(msg_para[i].auto_sw_cnt + AUTO_SW_MODE_TIME);
        if (msg_para[i].overflow_value < msg_para[i].auto_sw_cnt) {
            if ((clk >= msg_para[i].overflow_value) && (clk < msg_para[i].auto_sw_cnt)) {
                goto mode_switch;
            }
        } else {
            if ((uint32_t)(clk - msg_para[i].auto_sw_cnt) >= AUTO_SW_MODE_TIME) {
            mode_switch:
                msg_para[i].auto_sw_cnt = clk;
                #if MSG_AUTO_STOP
                    if(--msg_para[i].work_time == 0){
                        Msg_Set_On_Or_Off(i, MSG_CLOSE);
                        return;
                    }
                #endif
                if (msg_para[i].mode_sw_type == MSG_AUTO) {
                    if (++msg_para[i].mode > MSG_MODE_NUM) {
                        msg_para[i].mode = MSG_MODE_1;
                        msg_para[i].fre_cnt = 0;
                        msg_para[i].mode_type = 0;
                    }
                    #if MSG_MODE2_ADJUSTABLE_SPEED
                        // 在自动模式下，切换到变速的模式2之前，先将模式2内切换部位的模式时间置位为零
                        if (msg_para[i].mode == MSG_MODE_2) {
                            msg_para[i].mode2_sw_time = 0;
                        }
                    #endif
                } 
            }
        }
        
        // 在通过模式加/减函数切换到手动模式时，将模式内的部位模式切换置位为零，即从模式内的第一个部位模式开始切换
        if (msg_para[i].mode_sw_type == MSG_MANUAL) {
            if (msg_para[i].manual_sw_mode_flag) {
                msg_para[i].manual_sw_mode_flag = FALSE;
                msg_para[i].mode = msg_para[i].manual_mode;
                msg_para[i].fre_cnt = 0;
                msg_para[i].mode_type = 0;
            }
        }

		switch (msg_para[i].mode) {

			case MSG_MODE_1 : p_msg_mode = msg_mode1; break;

			case MSG_MODE_2 : p_msg_mode = msg_mode2; break;

			case MSG_MODE_3 : p_msg_mode = msg_mode3; break;

			case MSG_MODE_4 : p_msg_mode = msg_mode4; break;

			case MSG_MODE_5 : p_msg_mode = msg_mode5; break;

			case MSG_MODE_6 : p_msg_mode = msg_mode6; break;

			case MSG_MODE_7 : p_msg_mode = msg_mode7; break;

			case MSG_MODE_8 : p_msg_mode = msg_mode8; break;

			case MSG_MODE_9 : p_msg_mode = msg_mode9; break;

			case MSG_MODE_10 : p_msg_mode = msg_mode10; break;	

			default :
				break;
		}

        switch (msg_para[i].mode) {
            case MSG_MODE_1:
			case MSG_MODE_3:
			case MSG_MODE_4: 
			case MSG_MODE_5: 
			case MSG_MODE_6: 
			case MSG_MODE_7: 
			case MSG_MODE_8: 
			case MSG_MODE_9: 
			case MSG_MODE_10: {
                if ((msg_para[i].mode_sw_cnt + mode_sw_time[msg_para[i].mode - 1]) < msg_para[i].mode_sw_cnt) {
                    if (clk >= (msg_para[i].mode_sw_cnt + mode_sw_time[msg_para[i].mode - 1]) && (clk < msg_para[i].mode_sw_cnt)) {
                        goto mode_type_switch;
                    }
                } else {
                    if (mode_sw_time[msg_para[i].mode - 1] <= (uint32_t)(clk - msg_para[i].mode_sw_cnt)) {
                    mode_type_switch:

                    #if MSG_MODE2_ADJUSTABLE_SPEED
                        if (msg_para[i].mode == MSG_MODE_2) {
                            static uint8_t sw_mode2_delay_time = 0;
                            if (msg_para[i].mode2_sw_time == 0) {
                                sw_mode2_delay_time = 0;
                            }
                            if (++sw_mode2_delay_time > (3 * msg_para[i].msg_pos_num)) {
                                sw_mode2_delay_time = 1;
                                if (++msg_para[i].mode2_sw_cnt > (sizeof(mode2_sw_type_time) / sizeof(mode2_sw_type_time[0])) - 1) {
                                    msg_para[i].mode2_sw_cnt = 0;
                                }
                            }			
                            msg_para[i].mode2_sw_time = mode2_sw_type_time[msg_para[i].mode2_sw_cnt];		
                        }
                    #endif

                        msg_para[i].mode_sw_cnt = clk;

                        // 将原模式一切换时间恢复!
                        if (msg_para[i].mode == MSG_MODE_1) {
                            mode_sw_time[MSG_MODE_1 - 1] = msg_para[i].mode1_sw_time_backups;
                        }

                    #if MSG_POINT_CONTROL
                        if (msg_para[i].point_en_flag) {
                            msg_para[i].pos.pos_ctl = 0;

                            #if MSG_HEAD_CONTROL
                                if (msg_para[i].head_en_flag) {
                            #endif
                                #if MSG_STATUS_CHECK
                                    if (!msg_para[i].msg_install.pos.head) {
                                #endif
                                        if (msg_para[i].msg_point.pos.head) {
                                            msg_para[i].pos.pos_ctl |= (p_msg_mode [msg_para[i].mode_type] & MSG_HEAD_POS_CMD);
                                        }
                                #if MSG_STATUS_CHECK
                                    }
                                #endif
                            #if MSG_HEAD_CONTROL
                                } else {
                                    msg_para[i].pos.pos_ctl |= 0X00;
                                }
                            #endif

                            #if MSG_STATUS_CHECK
                                if (!msg_para[i].msg_install.pos.back) {
                            #endif
                                    if (msg_para[i].msg_point.pos.back) {
                                        msg_para[i].pos.pos_ctl |= (p_msg_mode [msg_para[i].mode_type] & MSG_BACK_POS_CMD);
                                    }
                            #if MSG_STATUS_CHECK
                                }
                                if (!msg_para[i].msg_install.pos.loin) {
                            #endif
                                    if (msg_para[i].msg_point.pos.loin) {
                                        msg_para[i].pos.pos_ctl |= (p_msg_mode [msg_para[i].mode_type] & MSG_LOIN_POS_CMD);
                                    }
                            #if MSG_STATUS_CHECK
                                }
                                if (!msg_para[i].msg_install.pos.hip) {
                            #endif
                                    if (msg_para[i].msg_point.pos.hip) {
                                        msg_para[i].pos.pos_ctl |= (p_msg_mode [msg_para[i].mode_type] & MSG_HIP_POS_CMD);
                                    }
                            #if MSG_STATUS_CHECK
                                }
                                if (!msg_para[i].msg_install.pos.leg) {
                            #endif
                                    if (msg_para[i].msg_point.pos.leg) {
                                        msg_para[i].pos.pos_ctl |= (p_msg_mode [msg_para[i].mode_type] & MSG_LEG_POS_CMD);
                                    }
                            #if MSG_STATUS_CHECK
                                }
                                if (!msg_para[i].msg_install.pos.foot) {
                            #endif
                                    if (msg_para[i].msg_point.pos.foot) {
                                        msg_para[i].pos.pos_ctl |= (p_msg_mode [msg_para[i].mode_type] & MSG_FOOT_POS_CMD);
                                    }
                            #if MSG_STATUS_CHECK
                                }
                            #endif
                        } else {
                    #endif
                            msg_para[i].pos.pos_ctl = 0;
                            #if MSG_HEAD_CONTROL
                                if (msg_para[i].head_en_flag) {
                            #endif
                                #if MSG_STATUS_CHECK
                                    if (!msg_para[i].msg_install.pos.head) {
                                #endif
                                        msg_para[i].pos.pos_ctl |= (p_msg_mode [msg_para[i].mode_type] & MSG_HEAD_POS_CMD);
                                #if MSG_STATUS_CHECK
                                    }
                                #endif
                            #if MSG_HEAD_CONTROL
                                } else {
                                    msg_para[i].pos.pos_ctl |= 0X00;
                                }
                            #endif

                            #if MSG_STATUS_CHECK
                                if (!msg_para[i].msg_install.pos.back) {
                            #endif
                                    msg_para[i].pos.pos_ctl |= (p_msg_mode [msg_para[i].mode_type] & MSG_BACK_POS_CMD);
                            #if MSG_STATUS_CHECK
                                }
                                if (!msg_para[i].msg_install.pos.loin) {
                            #endif
                                    msg_para[i].pos.pos_ctl |= (p_msg_mode [msg_para[i].mode_type] & MSG_LOIN_POS_CMD);
                            #if MSG_STATUS_CHECK
                                }
                                if (!msg_para[i].msg_install.pos.hip) {
                            #endif
                                    msg_para[i].pos.pos_ctl |= (p_msg_mode [msg_para[i].mode_type] & MSG_HIP_POS_CMD);
                            #if MSG_STATUS_CHECK
                                }
                                if (!msg_para[i].msg_install.pos.leg) {
                            #endif
                                    msg_para[i].pos.pos_ctl |= (p_msg_mode [msg_para[i].mode_type] & MSG_LEG_POS_CMD);
                            #if MSG_STATUS_CHECK
                                }
                                if (!msg_para[i].msg_install.pos.foot) {
                            #endif
                                    msg_para[i].pos.pos_ctl |= (p_msg_mode [msg_para[i].mode_type] & MSG_FOOT_POS_CMD);
                            #if MSG_STATUS_CHECK
                                }
                            #endif
                    #if MSG_POINT_CONTROL
                        }
                    #endif
                    
                        Msg_Sw_Mode_Type(i, msg_para[i].mode);

                        #if MSG_POS_LED
                            msg_para[i].msg_pos_led = msg_para[i].pos.pos_ctl;
                        #endif

                        #if MSG_MODE10_ADJUSTABLE_STRE
                            // 马达模式10的强度变化控制
                            if (msg_para[i].mode == MSG_MODE_10) {
                                if (++msg_para[i].mode10_sw_stre_cnt > (sizeof(mode10_sw_intensity) / sizeof(mode10_sw_intensity[0])) - 1) {
                                    msg_para[i].mode10_sw_stre_cnt = 0;
                                }
                                
                                msg_para[i].intensity = mode10_sw_intensity[msg_para[i].mode10_sw_stre_cnt];
                            } else {
                                // 在退出马达模式10之后，将马达强度恢复为进入模式10前的强度
                                if (msg_para[i].intensity != msg_para[i].intensity_backups) {
                                    msg_para[i].intensity = msg_para[i].intensity_backups;
                                }
                            }
                        #endif
                           
                        #if MSG_OVER_CURRENT_DETECTION
                            #if MSG_POINT_CONTROL
                            // 在进入到点动模式时，将马达过流检测阈值调整为点动模式下的阈值，下同
                            if (msg_para[i].point_en_flag) {
                                if (msg_para[i].oc_flag == MSG_UNOVER) {
                                    Msg_Set_Oc_Value(i, POINT_MODE);
                                }
                            } else {
                            #endif
                                // 在退出点动模式之后，将马达过流检测阈值调整为普通模式下的阈值，下同
                                if (msg_para[i].oc_flag == MSG_UNOVER) {
                                    Msg_Set_Oc_Value(i, NORMAL_MODE);
                                }
                            #if MSG_POINT_CONTROL
                            }
                            #endif
                        #endif
                    }
                }
                break;
            }
            case MSG_MODE_2: {
                // 马达模式2的变速控制
                    #if MSG_MODE2_ADJUSTABLE_SPEED
                    if ((msg_para[i].mode_sw_cnt + msg_para[i].mode2_sw_time) < msg_para[i].mode_sw_cnt) {
                        if (clk >= (msg_para[i].mode_sw_cnt + msg_para[i].mode2_sw_time) && (clk < msg_para[i].mode_sw_cnt)) {
                            goto mode_type_switch;
                        }
                    } else {
                        if (msg_para[i].mode2_sw_time <= (uint32_t)(clk - msg_para[i].mode_sw_cnt)) {
                            goto mode_type_switch;
                        }
                    }
                    #else
                    if ((msg_para[i].mode_sw_cnt + mode_sw_time[msg_para[i].mode - 1]) < msg_para[i].mode_sw_cnt) {
                        if (clk >= (msg_para[i].mode_sw_cnt + mode_sw_time[msg_para[i].mode - 1]) && (clk < msg_para[i].mode_sw_cnt)) {
                            goto mode_type_switch;
                        }
                    } else {
                        if (mode_sw_time[msg_para[i].mode - 1] <= (uint32_t)(clk - msg_para[i].mode_sw_cnt)) {
                            goto mode_type_switch;
                        }
                    }
                    #endif
                break;
            }
            default: {
                msg_para[i].mode = MSG_MODE_1; 
                break;
            }
        }
    }
}

void Msg_Process(void)
{
    Msg_Scan();
    #if MSG_OVER_CURRENT_DETECTION
        Msg_Over_Current_Detection_Scan();
    #endif
}

void Msg_Int_Process(void)
{
    for (uint8_t i = 0; i < MSG_DEV_NUM; i++) {
        if (msg_para[i].suspend_flag) 
            continue;
        if (msg_para[i].work_sta) {
            if (msg_para[i].fre_cnt++ < msg_para[i].intensity) {
				#if MSG_OVER_CURRENT_DETECTION
                    // 当马达进入过流检测模式时，正常模式无法驱动马达工作
                    if (!msg_para[i].oc_flag) {
				#endif
                        #if MSG_HEAD_CONTROL
                            if (msg_para[i].head_en_flag) {
                        #endif
                                #if MSG_OVER_CURRENT_DETECTION
                                    if (!msg_para[i].oc.pos.head) {
                                        // 避免当模拟比较器中断发生在该函数内（即发生中断嵌套时）所造成的bug（没有发生短路的马达部位被判断为短路的bug），下同
                                        if (!msg_para[i].oc_flag) {
                                #endif
                                            Msg_Opt_Port(i, MSG_POS_HEAD, msg_para[i].pos.pos.head);
                                #if MSG_OVER_CURRENT_DETECTION
                                        } else {
                                            Msg_Opt_Port(i, MSG_POS_HEAD, MSG_CLOSE);
                                            return;
                                        }
                                    } else {
                                        Msg_Opt_Port(i, MSG_POS_HEAD, MSG_CLOSE);
                                    }
                                #endif
                        #if MSG_HEAD_CONTROL
                            } else {
                                Msg_Opt_Port(i, MSG_POS_HEAD, MSG_CLOSE);			
                            }
                        #endif
                        #if MSG_OVER_CURRENT_DETECTION
                            if (!msg_para[i].oc.pos.back) {
                                if (!msg_para[i].oc_flag) {
                        #endif
                                    Msg_Opt_Port(i, MSG_POS_BACK, msg_para[i].pos.pos.back);
                        #if MSG_OVER_CURRENT_DETECTION
                                    } else {
                                        Msg_Opt_Port(i, MSG_POS_BACK, MSG_CLOSE);
                                        return;
                                    }
                            } else {
                                Msg_Opt_Port(i, MSG_POS_BACK, MSG_CLOSE);
                            }		
                            if (!msg_para[i].oc.pos.loin) {
                                if (!msg_para[i].oc_flag) {
                        #endif
                                    Msg_Opt_Port(i, MSG_POS_LOIN, msg_para[i].pos.pos.loin);
                        #if MSG_OVER_CURRENT_DETECTION
                                } else {
                                    Msg_Opt_Port(i, MSG_POS_LOIN, MSG_CLOSE);
                                    return;
                                }
                            } else {
                                Msg_Opt_Port(i, MSG_POS_LOIN, MSG_CLOSE);
                            }
                            if (!msg_para[i].oc.pos.hip) {
                                if (!msg_para[i].oc_flag) {
                        #endif
                                    Msg_Opt_Port(i, MSG_POS_HIP, msg_para[i].pos.pos.hip);
                        #if MSG_OVER_CURRENT_DETECTION
                                } else {
                                    Msg_Opt_Port(i, MSG_POS_HIP, MSG_CLOSE);
                                    return;
                                }
                            } else {
                                Msg_Opt_Port(i, MSG_POS_HIP, MSG_CLOSE);
                            }		
                            if (!msg_para[i].oc.pos.leg) {
                                if (!msg_para[i].oc_flag) {
                        #endif
                                    Msg_Opt_Port(i, MSG_POS_LEG, msg_para[i].pos.pos.leg);	
                        #if MSG_OVER_CURRENT_DETECTION				
                                } else {
                                    Msg_Opt_Port(i, MSG_POS_LEG, MSG_CLOSE);
                                    return;
                                }
                            } else {
                                Msg_Opt_Port(i, MSG_POS_LEG, MSG_CLOSE);
                            }
                            if (!msg_para[i].oc.pos.foot) {
                                if (!msg_para[i].oc_flag) {
                        #endif
                                    Msg_Opt_Port(i, MSG_POS_FOOT, msg_para[i].pos.pos.foot);
                        #if MSG_OVER_CURRENT_DETECTION
                                } else {
                                    Msg_Opt_Port(i, MSG_POS_FOOT, MSG_CLOSE);
                                    return;
                                }
                            } else {
                                Msg_Opt_Port(i, MSG_POS_FOOT, MSG_CLOSE);
                            }
                    }
                #endif
            } else {
                #if MSG_OVER_CURRENT_DETECTION
                    if (!msg_para[i].oc_flag) {
                #endif
                        Msg_Opt_Port(i, MSG_POS_HEAD, MSG_CLOSE);
                        Msg_Opt_Port(i, MSG_POS_BACK, MSG_CLOSE);
                        Msg_Opt_Port(i, MSG_POS_LOIN, MSG_CLOSE);
                        Msg_Opt_Port(i, MSG_POS_HIP, MSG_CLOSE);
                        Msg_Opt_Port(i, MSG_POS_LEG, MSG_CLOSE);
                        Msg_Opt_Port(i, MSG_POS_FOOT, MSG_CLOSE);	
                        if (MSG_VIBRATION_PERIOD < msg_para[i].fre_cnt) 
                            msg_para[i].fre_cnt = 0;
                #if MSG_OVER_CURRENT_DETECTION
                    }
                #endif
            }
        }
    }
}
